from PyQt4 import QtGui, QtCore
import OpenGL.GL as GL
import lucid.core
import osg2
from pydispatch import dispatcher

import geom_editor_base

class UberGeometryEditor(object):
   def __init__(self, geomFC):
      self.mGeom = geomFC
      
      self.setupInterface()
   
   def setupInterface(self):
      self.widget = UberGeometryWidget(self)
      
      self.mTypeModel = TypesModel()
      self.mLengthModel = LengthsModel()      
      self.mVertDataModel = VertexDataModel()
      self.mIndDataModel = IndicesDataModel()
      
      for x in [self.mTypeModel, self.mLengthModel, self.mIndDataModel, self.mVertDataModel]:
         x.setGeom(self.mGeom)
      
      self.widget.mTypeTable.setModel(self.mTypeModel)
      self.widget.mLengthTable.setModel(self.mLengthModel)
      self.widget.mIndicesTable.setModel(self.mIndDataModel)
      self.widget.mDataTable.setModel(self.mVertDataModel)      
      
      self.widget.show()
      

class UberGeometryWidget(QtGui.QWidget, geom_editor_base.Ui_Form):
   def __init__(self, editor, parent=None):
      QtGui.QWidget.__init__(self, parent)
      self.editor = editor
      self.setupUi(self)
      


class TypesModel(QtCore.QAbstractTableModel):
   def __init__(self,parent=None):
      QtCore.QAbstractTableModel.__init__(self,parent)
      
      self.typeMap = {}   # map type id to name
      for n in ["GL_POINTS","GL_LINES","GL_LINE_STRIP","GL_LINE_LOOP",
                "GL_TRIANGLES","GL_TRIANGLE_STRIP","GL_TRIANGLE_FAN",
                "GL_QUADS","GL_QUAD_STRIP","GL_POLYGON"]:
         val = getattr(GL,n)
         self.typeMap[val] = n
   
   def setGeom(self, geomFC):
      self.geom = geomFC
      self.reset()
   
   def rowCount(self,parent):
      if self.geom:
         return self.geom.getTypes().size()
      else:
         return 0
   
   def columnCount(self,parent):
      return 1

   def headerData(self, section, orientation, role):
      if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:         
         return QtCore.QVariant("Types")
      return QtCore.QVariant()

   def data(self, index, role):
      if not self.geom or not index.isValid():
         return QtCore.QVariant()
      elif role == QtCore.Qt.DisplayRole:
         i = index.row()
         val = self.geom.getTypes().getValue(i)
         type_str = self.typeMap.get(val,str(val))
         return QtCore.QVariant(type_str)
      else:
         return QtCore.QVariant()


class LengthsModel(QtCore.QAbstractTableModel):
   def __init__(self,parent=None):
      QtCore.QAbstractTableModel.__init__(self,parent)
   
   def setGeom(self, geomFC):
      self.geom = geomFC
      self.reset()
   
   def rowCount(self,parent):
      if self.geom:
         return self.geom.getLengths().size()
      else:
         return 0
   
   def columnCount(self,parent):
      return 1

   def headerData(self, section, orientation, role):
      if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:         
         return QtCore.QVariant("Lengths")
      return QtCore.QVariant()

   def data(self, index, role):
      if not self.geom or not index.isValid():
         return QtCore.QVariant()
      elif role == QtCore.Qt.DisplayRole:
         i = index.row()
         return QtCore.QVariant(str(self.geom.getLengths().getValue(i)))
      else:
         return QtCore.QVariant()


class IndicesDataModel(QtCore.QAbstractTableModel):
   def __init__(self,parent=None):
      QtCore.QAbstractTableModel.__init__(self,parent)
      self.setupInternalData()
   
   def setupInternalData(self):
      self.headers = ["0:Pos","1:Weights","2:Normals","3:Color","4:SecColor","5:Fog",
                      "6:---","7:---"]
      for x in range(8):
         self.headers.append("%s:Tex%s"%((x+8),x))
      self.indVecs = [None]*16      # The property vectors
      self.indSizes = [0]*16        # The length of the prop vectors      
      self.maxSize = 0              # Maximum length of properties
   
   def setGeom(self, geomFC):
      self.geom = geomFC
      self.updateInternalData()
      self.reset()
   
   def updateInternalData(self):
      """ Update the internal data we use for this thing. """
      assert self.geom != None
      self.indVecs = [None]*16
      self.indSizes = [0]*16
      
      for x in range(16):
         indices = self.geom.getIndex(x)
         self.indVecs[x] = indices
         if indices:
            self.indSizes[x] = indices.size()            
            
      self.maxSize = max(self.indSizes)      

   def rowCount(self,parent):
      return self.maxSize
   
   def columnCount(self,parent):
      use_all = False
      first_set = self.indVecs[0]
      for v in self.indVecs[1:]:
         if v != first_set:
            use_all = True
      
      if use_all:
         return len(self.indVecs)
      else:
         return 1

   def headerData(self, section, orientation, role):
      if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:         
         return QtCore.QVariant(str(self.headers[section]))
      elif orientation == QtCore.Qt.Vertical and role == QtCore.Qt.DisplayRole:
         return QtCore.QVariant(str(section))
      return QtCore.QVariant()

   def data(self, index, role):
      if not self.geom or not index.isValid():
         return QtCore.QVariant()
      elif role == QtCore.Qt.DisplayRole:
         row = index.row()
         col = index.column()
         
         # If no data or out of range
         if (not self.indVecs[col]) or (self.indSizes[col] < row):
            return QtCore.QVariant(str("--"))
         
         return QtCore.QVariant(str(self.indVecs[col].getValue(row)))
      else:
         return QtCore.QVariant()
      
      


class VertexDataModel(QtCore.QAbstractTableModel):
   def __init__(self,parent=None):
      QtCore.QAbstractTableModel.__init__(self,parent)
      self.setupInternalData()
   
   def setupInternalData(self):
      self.headers = ["0:Pos","1:Weights","2:Normals","3:Color","4:SecColor","5:Fog",
                      "6:---","7:---"]
      for x in range(8):
         self.headers.append("%s:Tex%s"%((x+8),x))
      self.propVectors = [None]*16      # The property vectors
      self.propSizes = [0]*16           # The length of the prop vectors
      self.propVecDim = [4]*16          # The size of the vectors
      self.maxSize = 0                  # Maximum length of properties
   
   def setGeom(self, geomFC):
      self.geom = geomFC
      self.updateInternalData()
      self.reset()
   
   def updateInternalData(self):
      """ Update the internal data we use for this thing. """
      assert self.geom != None
      self.propVectors = [None]*16
      self.propSizes = [0]*16
      
      for x in range(16):
         vec = self.geom.getProperty(x)
         self.propVectors[x] = vec
         if vec:
            self.propSizes[x] = vec.size()
            self.propVecDim[x] = vec.getDimension()
      
      self.maxSize = max(self.propSizes)      

   def rowCount(self,parent):
      return self.maxSize
   
   def columnCount(self,parent):
      return len(self.propVectors)

   def headerData(self, section, orientation, role):
      if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:         
         return QtCore.QVariant(str(self.headers[section]))
      elif orientation == QtCore.Qt.Vertical and role == QtCore.Qt.DisplayRole:
         return QtCore.QVariant(str(section))
      return QtCore.QVariant()

   def data(self, index, role):
      if not self.geom or not index.isValid():
         return QtCore.QVariant()
      elif role == QtCore.Qt.DisplayRole:
         row = index.row()
         col = index.column()
         
         # If no data or out of range
         if (not self.propVectors[col]) or (self.propSizes[col] < row):
            return QtCore.QVariant(str("--"))
                  
         if 2 == self.propVecDim[col]:
            vec_val = self.propVectors[col].getValue_Vec2f(row)
            vec_str = "(%.3s, %.3s)"%(vec_val[0],vec_val[1])
         elif 3 == self.propVecDim[col]:
            vec_val = self.propVectors[col].getValue_Vec3f(row)
            vec_str = "(%.3s, %.3s, %.3s)"%(vec_val[0],vec_val[1],vec_val[2])
         else:
            vec_val = self.propVectors[col].getValue_Vec4f(row)
            vec_str = "(%.3s, %.3s, %.3s, %.3s)"%(vec_val[0],vec_val[1],vec_val[2],vec_val[3])
            
         return QtCore.QVariant(vec_str)
      else:
         return QtCore.QVariant()
      
      